package com.cxd.performance.utils;


import com.cxd.performance.annotation.ExcelField;
import com.cxd.performance.annotation.ExcelSelect;
import com.cxd.performance.enums.DatePatternEnum;
import com.cxd.performance.enums.ExcelCodeEnum;
import com.cxd.performance.enums.ExcelVersionEnum;
import com.cxd.performance.exception.BusinessException;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.hssf.usermodel.DVConstraint;
import org.apache.poi.hssf.usermodel.HSSFDataValidation;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddressList;
import org.apache.poi.xssf.usermodel.*;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

/**
 * @author:calvin
 * @date: 2019-09-08 10:03
 */
@Slf4j
public class ExcelCommonUtils {

    private final static List<String> dateTypeList = Arrays.asList("Date","date","Time","time");

    private final static String XLS = "xls";

    private final static String XLSX = "xlsx";

    private ExcelCommonUtils() {}

    /**
     *  根据Excel版本创建workbook:
     *  book （HSSFWorkbook=2003/xls、XSSFWorkbook=2007/xlsx）
     *
     * @param excelVersion
     * @return
     */
    public static Workbook getWorkbook(String excelVersion) {

        Workbook workbook = null;
        switch (excelVersion) {
            case XLS : workbook = new HSSFWorkbook();
                break;

            case XLSX :
                workbook = new XSSFWorkbook();
                break;

            default:
                log.error("未知的Excel版本,请指定Excel版本");
                throw new BusinessException(ExcelCodeEnum.EXCEL_UNKNOW_VERSION);
        }
        return workbook;
    }


    /**
     *  绿色三角形处理
     */
    public static void formatValue(Field field, Object fieldValue, Cell cell) {

        if (null != fieldValue
                && ( fieldValue.getClass().equals(BigDecimal.class)
                || fieldValue.getClass().equals(Integer.class)
                || fieldValue.getClass().equals(Long.class)
                || fieldValue.getClass().equals(Short.class)
                || fieldValue.getClass().equals(Double.class)
                || fieldValue.getClass().equals(Float.class)
                || fieldValue.getClass().equals(int.class)
                || fieldValue.getClass().equals(long.class)
                || fieldValue.getClass().equals(short.class)
                || fieldValue.getClass().equals(double.class)
                || fieldValue.getClass().equals(float.class)
        )
        ) {
            cell.setCellType(CellType.NUMERIC);

        } else if (
                field.getName() != null
                        && (field.getName().contains(dateTypeList.get(0))
                        || field.getName().contains(dateTypeList.get(1)))
                        || field.getName().contains(dateTypeList.get(2))
                        || field.getName().contains(dateTypeList.get(3)) ) {
            cell.setCellType(CellType.NUMERIC);

        } else {
            cell.setCellType(CellType.STRING);
        }

        if (fieldValue != null) {

            if (fieldValue.getClass().equals(Date.class)) {
                ExcelField excelField = field.getAnnotation(ExcelField.class);
                String datePattern = DatePatternEnum.PATTERN_1.getValue();
                if (excelField != null && excelField.dateformat()!=null) {
                    datePattern = excelField.dateformat();
                }
                String value = new SimpleDateFormat(datePattern)
                        .format(fieldValue);
                value = LocalDateUtils.date2String(LocalDateUtils.string2Date(value,datePattern),datePattern);
                cell.setCellValue(value);

            } else if (fieldValue.getClass().equals(BigDecimal.class)) {
                Double newValue = ((BigDecimal) fieldValue).doubleValue();
                cell.setCellValue(newValue);

            } else if (fieldValue.getClass().equals(Integer.class)) {
                Double newValue = ((Integer) fieldValue).doubleValue();
                cell.setCellValue(newValue);

            } else if (fieldValue.getClass().equals(Long.class)) {
                Double newValue = ((Long) fieldValue).doubleValue();
                cell.setCellValue(newValue);

            } else if (fieldValue.getClass().equals(Short.class)) {
                Double newValue = new BigDecimal(String.valueOf((Short) fieldValue)).doubleValue();
                cell.setCellValue(newValue);

            } else if (fieldValue.getClass().equals(Double.class)) {
                Double newValue = ((Double) fieldValue);
                cell.setCellValue(newValue);

            } else if (fieldValue.getClass().equals(Float.class)) {
                Double newValue = new BigDecimal(String.valueOf((Float) fieldValue)).doubleValue();
                cell.setCellValue(newValue);

            }
            else {
                String value = String.valueOf(fieldValue);
                cell.setCellValue(value);

            }

        } else {
            String value = "";
            cell.setCellValue(value);

        }

    }

    /**
     *  设置下拉框
     */
    public static void setColumnSelect(String excelVersion, Sheet sheet, List<Field> fields) {
        Field field = fields.get(0);
        ExcelSelect excelSelect = field.getAnnotation(ExcelSelect.class);
        if (null != excelSelect) {

            ExcelField excelField = field.getAnnotation(ExcelField.class);
            if (excelField.index() < 0) {
                log.error("[导出Excel模板],列索引不能为空");
                throw new BusinessException(ExcelCodeEnum.EXCEL_SELECT_INDEX_NONULL);
            }

            DataValidation data_validation_list = null;
            switch (excelVersion) {
                case XLS :
                    DVConstraint constraint = DVConstraint
                            .createExplicitListConstraint(excelSelect.selectList());
                    CellRangeAddressList regions = new CellRangeAddressList(excelSelect.firstRow(),
                            excelSelect.endRow(), excelField.index(), excelField.index());
                    data_validation_list = new HSSFDataValidation(regions, constraint);
                    break;
                case XLSX:
                    XSSFDataValidationHelper dvHelper = new XSSFDataValidationHelper((XSSFSheet)sheet);
                    XSSFDataValidationConstraint dvConstraint = (XSSFDataValidationConstraint) dvHelper
                            .createExplicitListConstraint(excelSelect.selectList());
                    CellRangeAddressList addressList = new CellRangeAddressList(excelSelect.firstRow(),
                            excelSelect.endRow(), excelField.index(), excelField.index());
                    data_validation_list = (XSSFDataValidation) dvHelper.createValidation(
                            dvConstraint, addressList);
                    break;
                default:
                    log.error("未知的Excel版本");
                    throw new BusinessException(ExcelCodeEnum.EXCEL_UNKNOW_VERSION);
            }

            sheet.addValidationData(data_validation_list);
        }
    }

    public static String getExcelVersion(Class<?> sheetClass,String fileName) {
        if (fileName.contains(ExcelVersionEnum.XLS.getValue())) {

            return ExcelVersionEnum.XLS.getValue();
        }else if (fileName.contains(ExcelVersionEnum.XLSX.getValue())) {

            return ExcelVersionEnum.XLSX.getValue();
        }else {

            throw new BusinessException(ExcelCodeEnum.EXCEL_UNKNOW_VERSION);
        }

    }

    public static String getExcelVersion(String fileName) {
        if (BaseStringUtils.isEmpty(fileName)) {
            return null;
        }
        String preFileName = fileName.substring(0,fileName.indexOf("."));
        String targetVersion = fileName.substring(preFileName.length() + 1, fileName.length());
        return targetVersion;
    }
}
